/**
 * gamepad constant variables
 */
const intervalTime = 20 // 60fps = 16.667 us
const threshold = 0.45
const deadArea = 0.0001
const vibrateTime = 200 // unit: us

let glbInterval
let isConnected = false

let direction
let moveStep

/**
 * velocity control varibles
 */
let bouncing = false
let velocity
let bounceWay = Bounce.still
const initVlc = 120
const acceleration = 5
/* acceleration must be factor of initVlc, that is:
  initVlc % acceleration = 0 */

/**
 * gamepad lifecycle detect
 */
window.addEventListener("gamepadconnected", (event) => {
  console.log("A Gamepad Connected!")
  console.log(event.gamepad)
  isConnected = true
})

window.addEventListener("gamepaddisconnected", (event) => {
  console.log("A Gamepad Disconnected!")
  console.log(event.gamepad)
  clearInterval(glbInterval)
  isConnected = false
})

const joystick = {
  horizen: 0.0,
  vertic: 0.0
}

const buttons = {
  A: true
}

function doVibrate(gamepad) {
  gamepad.vibrationActuator.playEffect("dual-rumble", {
    startDelay: 0,
    duration: vibrateTime,
    weakMagnitude: 1.0,
    strongMagnitude: 1.0
  })
}

function gamepadControl() {
  if (!isConnected)
    return

  let gamepad = navigator.getGamepads()[0]

  joystick.horizen = gamepad.axes[0]
  joystick.vertic  = gamepad.axes[1]
  buttons.A = gamepad.buttons[0].pressed

  /* Handle bouncing */
  if (!bouncing && buttons.A) {
    /* Trigger boucing and init */
    velocity = initVlc
    bounceWay = Bounce.lifting
    bouncing = true
  }
  if (bouncing) {
    if (bounceWay == Bounce.lifting) {
      if (velocity - acceleration > 0) {
        velocity -= acceleration
      }else {
        velocity = 0
        bounceWay = Bounce.dropping
      }
    }else if (bounceWay == Bounce.dropping) {
      if (velocity + acceleration < initVlc) {
        velocity += acceleration
      }else {
        velocity = initVlc
        bounceWay = Bounce.still
        bouncing = false
      }
    }
  }

  /* Handle horizental moving */
  if (joystick.horizen > deadArea) {
    direction = Direction.right // move right
    if (joystick.horizen < threshold || bouncing)
      moveStep = 1 // slow move
    else
      moveStep = 3 // quick move
  }else if (joystick.horizen < -deadArea) {
    direction = Direction.left // move left
    if (joystick.horizen > -threshold || bouncing)
      moveStep = 1 // slow move
    else
      moveStep = 3 // quick move
  }else {
    direction = Direction.still
  }

  if (updateCanvas(
    bounceWay,
    velocity,
    direction,
    moveStep)
  ) {
    doVibrate(gamepad)
  }
}

/* main loop */
glbInterval = setInterval(gamepadControl, intervalTime)